﻿using log4net;
using Mangox.BLL.Mangox;
using Mangox.Common;
using Mangox.Common.Tookit;
using Mangox.Model.Common;
using Mangox.Model.MangoxDB;
using Mangox.Model.Stock;
using MGXAPI.BLL;
using MGXAPI.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Security.Cryptography;
using System.Web.Http;

namespace MGXAPI.Controllers.API.Mangox
{
    public class WeChatController : ApiController
    {
        private static string[] mgixbit8 = { "wx234e43589da394ff", "08b9588eac2fd021ebafe959718dabbc" };//source 8
        private static string[] mgixbit1 = { "wxbc36feabc7ecd6d1", "1740f6772a2cb534d94d868e54852811" };//1
        private static string[] mgixbit9 = { "", "" };//9
        protected static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        protected static string className = (new StackTrace()).GetFrame(1).GetMethod().ReflectedType.Name + "/";       //获取类名 
        private static string api_weixin = "https://api.weixin.qq.com/sns/jscode2session?{0}&js_code={1}&grant_type=authorization_code";
        private string api_acctoken = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&{0}";//暂时未用到
        private string api_release = "https://api.weixin.qq.com/wxa/release?access_token={0}";  //生效小程序

        //新用户转币公共账户,金额
        private string publicHash = "e6e0db9ef388b43d7d1111655db2effb3f4f1bd227bda45343aff5f5945b852a";
        private double defToAmount = 100;

        Random rd = new Random();


        #region 调用微信接口登录

        /// <summary>
        /// 微信登陆返回Openid
        /// http://localhost:13772/api/WeChat/Login
        /// 返回动态对象模型，不是jsonrequest，这是再控制器里面使用的
        /// </summary>
        /// <param name="resCode">wx.login 获取的code</param>
        /// <returns></returns>
        [HttpPost]
        public LoginResultModel_Wechar Login(RequestModel p)
        {
            //计时，运行时间，消耗时间，执行时间，耗时
            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();

            LoginResultModel_Wechar result = new LoginResultModel_Wechar();
            result.Data = new M_User();
            result.Code = -1;
            result.Code = 0;
            M_User user = null;

            string code = p.Param.ResCode;
            string encryptedData = p.Param.EncryptedData;
            string iv = p.Param.Iv;

            //ResCode = "0239k7uy0j91hh1BIWry0kifuy09k7uu";//test

            log.Info(className + $"Login signature-{p.Param.ResCode}");
            string openid = null;  //换取的openid
            JsonRequest request = new JsonRequest();
            string url = string.Format(api_weixin, GetwxUrl(p.Source), p.Param.ResCode);
            string ret_wx = null;
            string userHash = "";
            double amount = 0;
            bool isNewUser = false;//如果是新用户就不用查询余额

            try
            {
                //string jsonUser = "{\"ID\":0,\"UserID\":161278,\"LoginName\":\"161278\",\"Password\":null,\"UserName\":\"Jessy\",\"Session_key\":null,\"Openid\":\"odCMp4zvZZ1wJZBGNnrHlBxCvFgQ\",\"UnionId\":null,\"MgxHashID\":\"d99e7823b94629738f42a5f81f4c2b948542ae1ac2584d574f59951420baa17d\",\"ERCAddress\":null,\"Source\":null,\"IsAuth\":null,\"State\":1,\"Mobile\":null,\"Email\":null,\"NickName\":\"Jessy\",\"AvatarUrl\":\"https://wx.qlogo.cn/mmopen/vi_32/DYAIOgq83epqTkIy4WiaJVc0WMOrvwORdXibnmZFHgTq8qiapUrj01fFn5FmR2O4fcJceYa3VURFMTTfNZuuTo8iaQ/132\",\"Gender\":null,\"City\":\"San Francisco City\",\"Province\":\"California\",\"Country\":\"US\",\"Language\":\"en\",\"CreateTime\":\"2019-06-29T17:29:15.5067633+08:00\",\"LoginTime\":\"2019-06-29T17:29:15.5067633+08:00\",\"LastLoginTime\":\"2019-06-29T17:29:15.5067633+08:00\",\"LoginCount\":1,\"Remark\":null}";
                //string jsonUser = "{\"ID\":0,\"UserID\":5757256,\"LoginName\":\"5757256\",\"Password\":null,\"UserName\":\"林姿辛\",\"Session_key\":null,\"Openid\":\"odCMp4xYzQ-bGYphjJZWWibcB9qI\",\"UnionId\":null,\"MgxHashID\":\"86b1c1e2b9114082d688f0b0d85c7dd29a9d5d1123d0dfd691dc73e4c492a7f2\",\"ERCAddress\":null,\"Source\":null,\"IsAuth\":null,\"State\":1,\"Mobile\":null,\"Email\":null,\"NickName\":\"林姿辛\",\"AvatarUrl\":\"https://wx.qlogo.cn/mmhead/ibKgNjpmV8bggqkLibmIXBnVcBvozPHg8bGUm3KCibl20g/132\",\"Gender\":null,\"City\":\"\",\"Province\":\"\",\"Country\":\"\",\"Language\":\"zh_CN\",\"CreateTime\":\"2019-06-27T12:36:08.3723647+08:00\",\"LoginTime\":\"2019-06-27T12:36:08.3723647+08:00\",\"LastLoginTime\":\"2019-06-27T12:36:08.3723647+08:00\",\"LoginCount\":1,\"Remark\":null}";
                //user = JsonCommon.JsonDeserialize<M_User>(jsonUser);
                //var fl = new MgxUserBLL().AddUser(user);


                log.Info($"登陆参数-{JsonCommon.ToJson(p)}");

                ret_wx = request.Get(url);
                log.Info(className + $"Login result-{ret_wx}");

                var loginModel = JsonCommon.JsonToMode<WxLoginParam>(ret_wx);
                MgxUserBLL bll = new MgxUserBLL();
                if (loginModel == null || string.IsNullOrEmpty(loginModel.openid))
                {
                    return null;
                }

                //解密用户信息

                var jiemi = AES_decrypt(encryptedData, loginModel.session_key, iv);




                openid = loginModel.openid;
                //判断是登陆过，是否是新用户
                //如果是新用户记录到用户表
                try
                {
                    user = bll.GetUserApplet(openid);
                }
                catch (Exception)
                {
                    return null;
                }

                bool flag = false;
                if (user == null)
                {
                    user = new M_User();
                    isNewUser = true;

                    log.Info($"openid【{openid}】未查询到用户，先创建mgo账号，再入库");

                    userHash = MgxBLL.CreateUserHash();
                    p.Param.MgxHashID = userHash;

                    user.UserID = new MgxUserBLL().CreateUserID();
                    user.LoginName = user.UserID.ToString();
                    user.MgxHashID = p.Param.MgxHashID;
                    user.Openid = openid;
                    user.Session_key = p.Param.Session_key;
                    user.UnionId = p.Param.UnionId;
                    user.CreateTime = DateTime.Now;
                    user.LoginTime = DateTime.Now;
                    user.LastLoginTime = DateTime.Now;
                    user.LoginCount = 1;
                    user.Source = (int)p.Source;

                    //可以更新的字段
                    user.NickName = p.Param.NickName;
                    user.UserName = p.Param.NickName;
                    user.AvatarUrl = p.Param.AvatarUrl;
                    user.Province = p.Param.Province;
                    user.City = p.Param.City;
                    user.Language = p.Param.Language;
                    user.Country = p.Param.Country;
                    user.State = 1;
                    user.AppType = (int)AppType.Mango;

                    try
                    {
                        flag = bll.AddUser(user);
                    }
                    catch (Exception)
                    {
                        return null;
                    }

                    log.Info($"创建新用户-{(flag ? "成功" : "失败")}，用户信息-{JsonCommon.ToJson(user)}");
                }
                else if (string.IsNullOrEmpty(user.UserName)
                    || string.IsNullOrEmpty(user.NickName)
                    || user.Source == null
                    || user.NickName != p.Param.NickName.ToString())
                {
                    userHash = user.MgxHashID;

                    user.LoginCount = ++user.LoginCount;
                    user.LastLoginTime = DateTime.Now;
                    user.Session_key = p.Param.Session_key;
                    user.UnionId = p.Param.UnionId;
                    user.NickName = p.Param.NickName;
                    user.AvatarUrl = p.Param.AvatarUrl;
                    user.Province = p.Param.Province;
                    user.City = p.Param.City;
                    user.Language = p.Param.Language;
                    user.Country = p.Param.Country;
                    user.Source = (int)p.Source;

                    if (string.IsNullOrWhiteSpace(user.UserName))
                    {
                        user.UserName = user.NickName;
                    }

                    try
                    {
                        flag = bll.UpdateUser(user, 1);
                        log.Info($"更新用户-{(flag ? "成功" : "失败")}，用户信息-{JsonCommon.ToJson(user)}");
                    }
                    catch (Exception)
                    {
                        return null;
                    }
                }
                else
                {
                    //写入登陆日志...
                    userHash = user.MgxHashID;
                    user.LoginCount = ++user.LoginCount;
                    user.LastLoginTime = DateTime.Now;
                    user.Session_key = p.Param.Session_key;

                    try
                    {
                        flag = bll.UpdateUser(user, 1);
                        log.Info($"更新用户 记录日志-{(flag ? "成功" : "失败")}，用户信息-{JsonCommon.ToJson(user)}");
                    }
                    catch (Exception)
                    {
                        return null;
                    }
                }

                var bllm = new MgxBLL();
                //查询账户余额，新用户就是0不用查询
                if (isNewUser)
                {
                    amount = 0;

                    /*
                    //新用户默认转币1000
                    var c = bllm.DefaultTransfer(publicHash, userHash, defToAmount);
                    amount += defToAmount;
                    //result.GiveMsg = "新用户金币大放送啦，" + amount + "金币已存入";
                    result.GiveMsg = $"新用户赠送{defToAmount}金币，已存入";
                    log.Info($"新用户赠送金币");
                    */
                }
                else
                {
                    var ret = bllm.GetBalanceIn(userHash);
                    if (ret == null || ret == "null" || ret == "NULL")
                    {
                        log.Info("矿池查询异常");
                        amount = 0;
                        result.Msg = "矿池接口异常";
                    }
                    else
                    {
                        amount = Convert.ToDouble(ret);
                    }

                    //如果用户是0，小于100就转
                    /*if (amount < 100)
                    {
                        var c = bllm.DefaultTransfer(publicHash, userHash, defToAmount);
                        if (c > 0) //转成功
                        {
                            amount += defToAmount;
                            result.GiveMsg = $"新用户赠送{defToAmount}金币，已存入";
                            log.Info($"用户金币少于100，赠送{defToAmount}个金币");
                        }
                    }*/
                }

                //每次使用记录到用户活跃表
                //var f = new UWPDeviceBLL().AddUserActive(new UserActive() { Source = SourceType.applet.ToString(), IsFirst = 1, Openid = openid });
                //if (!f)
                //    log.InfoFormat("AddUserActive fail");

                result.openid = openid;
                result.userHash = userHash;
                result.amount = double.Parse(amount.ToString("0.00"));

                //创建Token字符串
                result.Token = MgxCommBLL.CreateToken(user.UserID.ToString(), userHash);
                result.Data = new M_UserResult();
                ObjectReflection.AutoMapping(user, result.Data);
            }
            catch (Exception ex)
            {
                log.ErrorFormat(className + "微信登陆失败Login url-{0}，result-{1}，Fail-{2}", url, ret_wx, ex.ToString());
                //StockCommBLL.SendEmail("系统异常", "StockBLL/GetZdt", logInfo);
            }

            stopWatch.Stop();
            log.Info($"登陆耗时：{stopWatch.ElapsedMilliseconds / 1000}秒，{stopWatch.ElapsedMilliseconds}毫秒");

            return result;
        }

        /// <summary>
        /// 获取微信授权url
        /// </summary>
        /// <returns></returns>
        private string GetwxUrl(Source_MGX s)
        {
            string url = "appid={0}&secret={1}";
            switch (s)
            {
                case Source_MGX.applet :
                    url = string.Format(url, mgixbit1[0], mgixbit1[1]);
                    break;
                case Source_MGX.mgxbit :
                    url = string.Format(url, mgixbit8[0], mgixbit8[1]);
                    break;
                case Source_MGX.szsllkj :
                    url = string.Format(url, mgixbit9[0], mgixbit9[1]);
                    break;
                default:
                    break;
            }
            return url;
        }

        [HttpGet]
        public string GetAccess_token(string openid = null, string source = null)
        {
            log.Info(className + "GetAccess_token start");
            string access_token = null;
            JsonRequest request = new JsonRequest();
            string url = string.Format(api_acctoken, GetwxUrl(Source_MGX.applet));//暂时未用到
            string result = null;
            try
            {
                result = request.Get(url);
                log.Info(className + $"GetAccess_token result-{result}");

                var model = JsonCommon.JsonToMode<WxAccTokenResult>(result);
                access_token = model.access_token;
            }
            catch (Exception ex)
            {
                log.Error(className + $"GetAccess_token result-{result}，Fail-{ex.ToString()}");
            }

            return access_token;
        }

        /// <summary>
        /// 发布后小程序未生效调用
        /// </summary>
        /// <param name="access_token"></param>
        /// <returns></returns>
        [HttpGet]
        public string Release()
        {
            log.Info(className + "Release start");

            string access_token = GetAccess_token();
            JsonRequest request = new JsonRequest();
            string url = string.Format(api_release);
            string result = null;
            try
            {
                result = request.Get(url);
                log.Info(className + $"Release access_token-{access_token}，result-{result}");
            }
            catch (Exception ex)
            {
                log.Error(className + $"Release access_token-{access_token}，result-{result}, fail-{ex}");
            }
            return result;
        }


        /// <summary>
        /// C#/.net微信小程序encryptedData解密
        /// 获取以上参数
        /// 没有加密数据：{"nickName":"李强","gender":1,"language":"zh_CN","city":"Shenzhen","province":"Guangdong","country":"China","avatarUrl":"https://wx.qlogo.cn/mmopen/vi_32/U8ZFyRNZHRDy7nPUI2qNt19t5FmrSqPmLicvbe9tubEHAU6DF2MOKDliasuqSMJSu3aNgZfCVMHHqicMKvNtkaB3g/132"}
        /// 有加密数据：{"errMsg":"getUserInfo:ok","rawData":"{\"nickName\":\"name\",\"gender\":1,\"language\":\"zh_CN\",\"city\":\"Shenzhen\",\"province\":\"Guangdong\",\"country\":\"China\",\"avatarUrl\":\"https://wx.qlogo.cn/mmopen/vi_32/U8ZFyRNZHRDy7nPUI2qNt19t5FmrSqPmLicvbe9tubEHAU6DF2MOKDliasuqSMJSu3aNgZfCVMHHqicMKvNtkaB3g/2\"}","userInfo":{"nickName":"name","gender":1,"language":"zh_CN","city":"Shenzhen","province":"Guangdong","country":"China","avatarUrl":"https://wx.qlogo.cn/mmopen/vi_32/U8ZFyRNZHRDy7nPUI2qNt19t5FmrSqPmLicvbe9tubEHAU6DF2MOKDliasuqSMJSu3aNgZfCVMHHqicMKvNtkaB3g/3"},"signature":"9cc24a6750d96cd47b84ad46253c21184f8c7290","encryptedData":"Io11ioKOHDI4JYRODoSsa2b96bKka6+bn6qtj3km7NAi+zD+FmcjlpWYlk7WM+Ij3y7S1wmPDMCoA4uptv6zZD+H9w6lLEdzeaE51Kc0GPPSPtv/fE1jRhzkGA6leVjDXrY2/B0eMHFYBHWYZW22KGnX30UI9BP/k7/+ka9BgzulguvefwE4OiWbk/Z8hVHKhQy3C6AI1vPl5RuPrrngvIcBdnHcbGlcUPqU5HrqXtKiU+gusZGv4O5l5yx95oPnMKaX/RNc75N6FXLjLah1iZc2NwErSkpLJMdqLqhB+FsuZO6KvleVklEUkBVP+8nD2yG0NUwIuaWKSbO6E+YBesBFOCiNgmv2eG4Yg/g+5Pcl70YyQ9hkd8JQsESO1KECAiJ+luf07sZI0xzqRk658/EhrcZlNzB3IWB6D/66Zh84zGyBoxLC0CmPHUbvc6zQh0iHPa/IHB+cMvX01rfpDAyjJwwPPBi6nEq5mx++n04=","iv":"/mehdHoGRtPLeuJ0VP2QLg=="}
        /// </summary>
        /// <param name="encryptedDataStr"></param>
        /// <param name="session_key">和openid一起，换取后的key</param>
        /// <param name="iv"></param>
        /// <returns></returns>
        public string AES_decrypt(string encryptedDataStr, string session_key, string iv)
        {
            RijndaelManaged rijalg = new RijndaelManaged();
            //-----------------    
            //设置 cipher 格式 AES-128-CBC    

            rijalg.KeySize = 128;

            rijalg.Padding = PaddingMode.PKCS7;
            rijalg.Mode = CipherMode.CBC;

            rijalg.Key = Convert.FromBase64String(session_key);
            rijalg.IV = Convert.FromBase64String(iv);

            byte[] encryptedData = Convert.FromBase64String(encryptedDataStr);
            //解密    
            ICryptoTransform decryptor = rijalg.CreateDecryptor(rijalg.Key, rijalg.IV);

            string result;
            using (MemoryStream msDecrypt = new MemoryStream(encryptedData))
            {
                using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                {
                    using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                    {

                        result = srDecrypt.ReadToEnd();
                    }
                }
            }
            return result;
        }

        #endregion

        /// <summary>
        /// http://localhost:13772/api/WeChat/test
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public string test()
        {
            return "test";
        }
    }
}
